package src.main.java.com.huawei.demo;

import com.huaweicloud.sdk.core.auth.GlobalCredentials;
import com.huaweicloud.sdk.core.exception.ClientRequestException;
import com.huaweicloud.sdk.core.http.HttpConfig;
import com.huaweicloud.sdk.core.utils.StringUtils;
import com.huaweicloud.sdk.iam.v3.IamClient;
import com.huaweicloud.sdk.iam.v3.model.AgencyTokenAssumerole;
import com.huaweicloud.sdk.iam.v3.model.AgencyTokenAuth;
import com.huaweicloud.sdk.iam.v3.model.AgencyTokenIdentity;
import com.huaweicloud.sdk.iam.v3.model.AgencyTokenScope;
import com.huaweicloud.sdk.iam.v3.model.AgencyTokenScopeDomain;
import com.huaweicloud.sdk.iam.v3.model.AgencyTokenScopeProject;
import com.huaweicloud.sdk.iam.v3.model.AuthScope;
import com.huaweicloud.sdk.iam.v3.model.AuthScopeDomain;
import com.huaweicloud.sdk.iam.v3.model.AuthScopeProject;
import com.huaweicloud.sdk.iam.v3.model.KeystoneCreateAgencyTokenRequest;
import com.huaweicloud.sdk.iam.v3.model.KeystoneCreateAgencyTokenRequestBody;
import com.huaweicloud.sdk.iam.v3.model.KeystoneCreateAgencyTokenResponse;
import com.huaweicloud.sdk.iam.v3.model.KeystoneCreateScopedTokenRequest;
import com.huaweicloud.sdk.iam.v3.model.KeystoneCreateScopedTokenRequestBody;
import com.huaweicloud.sdk.iam.v3.model.KeystoneCreateScopedTokenResponse;
import com.huaweicloud.sdk.iam.v3.model.KeystoneCreateUserTokenByPasswordAndMfaRequest;
import com.huaweicloud.sdk.iam.v3.model.KeystoneCreateUserTokenByPasswordAndMfaRequestBody;
import com.huaweicloud.sdk.iam.v3.model.KeystoneCreateUserTokenByPasswordAndMfaResponse;
import com.huaweicloud.sdk.iam.v3.model.KeystoneCreateUserTokenByPasswordRequest;
import com.huaweicloud.sdk.iam.v3.model.KeystoneCreateUserTokenByPasswordRequestBody;
import com.huaweicloud.sdk.iam.v3.model.KeystoneCreateUserTokenByPasswordResponse;
import com.huaweicloud.sdk.iam.v3.model.MfaAuth;
import com.huaweicloud.sdk.iam.v3.model.MfaIdentity;
import com.huaweicloud.sdk.iam.v3.model.MfaTotp;
import com.huaweicloud.sdk.iam.v3.model.MfaTotpUser;
import com.huaweicloud.sdk.iam.v3.model.PwdAuth;
import com.huaweicloud.sdk.iam.v3.model.PwdIdentity;
import com.huaweicloud.sdk.iam.v3.model.PwdPassword;
import com.huaweicloud.sdk.iam.v3.model.PwdPasswordUser;
import com.huaweicloud.sdk.iam.v3.model.PwdPasswordUserDomain;
import com.huaweicloud.sdk.iam.v3.model.ScopeDomainOption;
import com.huaweicloud.sdk.iam.v3.model.ScopeProjectOption;
import com.huaweicloud.sdk.iam.v3.model.ScopedToken;
import com.huaweicloud.sdk.iam.v3.model.ScopedTokenAuth;
import com.huaweicloud.sdk.iam.v3.model.ScopedTokenIdentity;
import com.huaweicloud.sdk.iam.v3.model.TokenSocpeOption;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class CreateUserTokenSolution {
    private static final Logger logger = LoggerFactory.getLogger(CreateUserTokenSolution.class);

    public static void main(String[] args) {
        String ak = ""; // ak,必传
        String sk = ""; // sk,必传
        String domainId = ""; // 租户id:domainId,必传

        // 配置客户端属性
        HttpConfig config = HttpConfig.getDefaultHttpConfig();
        config.withIgnoreSSLVerification(true);

        // 创建认证
        GlobalCredentials auth = new GlobalCredentials()
            .withAk(ak)
            .withSk(sk)
            .withDomainId(domainId);

        // 创建请求客户端
        ArrayList<String> endpoints = new ArrayList<String>();
        endpoints.add(""); // 固定值，填入：https://iam.myhuaweicloud.com
        IamClient client = IamClient.newBuilder()
            .withCredential(auth)
            .withEndpoints(endpoints)
            .withHttpConfig(config).build();

        // 获取IAM用户Token（使用密码）
        createTokenByPassword(client);

        // 获取IAM用户Token（使用密码+虚拟MFA）
        createUserTokenByPasswordAndMfa(client);

        // 获取委托Token
        createAgencyToken(client);

        // 获取联邦认证scoped token
        createScopedToken(client);

    }

    private static void createTokenByPassword(IamClient client) {
        logger.info("####createTokenByPassword start!####");
        String userName = ""; // 用户名，必传
        String userPwd = ""; // 密码，必传
        String domainName = ""; // 租户名，必传

        KeystoneCreateUserTokenByPasswordRequest request = new KeystoneCreateUserTokenByPasswordRequest();
        KeystoneCreateUserTokenByPasswordRequestBody body = new KeystoneCreateUserTokenByPasswordRequestBody();

        // 设置scope，如果需要设置scop，完成setScope()方法。
        AuthScope authScope = setScope();

        PwdPasswordUserDomain domainUser = new PwdPasswordUserDomain();
        domainUser.withName(domainName);
        PwdPasswordUser userPassword = new PwdPasswordUser();
        userPassword.withDomain(domainUser)
            .withName(userName)
            .withPassword(userPwd);
        PwdPassword passwordIdentity = new PwdPassword();
        passwordIdentity.withUser(userPassword);
        List<PwdIdentity.MethodsEnum> listIdentityMethods = new ArrayList<PwdIdentity.MethodsEnum>();
        listIdentityMethods.add(PwdIdentity.MethodsEnum.fromValue("password"));
        PwdIdentity identityAuth = new PwdIdentity();
        identityAuth.withMethods(listIdentityMethods)
            .withPassword(passwordIdentity);
        PwdAuth authbody = new PwdAuth();
        authbody.withIdentity(identityAuth)
            .withScope(authScope);
        body.withAuth(authbody);
        request.withBody(body);
        try {
            KeystoneCreateUserTokenByPasswordResponse response = client.keystoneCreateUserTokenByPassword(request);
            logger.info(response.toString());
        } catch (ClientRequestException e) {
            LogError(e);
        }
    }

    private static void createUserTokenByPasswordAndMfa(IamClient client) {
        logger.info("####createUserTokenByPasswordAndMfa start!####");
        String userName = ""; // 用户名，必传
        String userPwd = ""; // 密码，必传
        String domainName = ""; // 租户名，必传
        String userId = ""; // 已开启虚拟MFA方式的登录保护的IAM用户ID，必传
        String passcode = ""; // 虚拟MFA验证码，必传

        KeystoneCreateUserTokenByPasswordAndMfaRequest request = new KeystoneCreateUserTokenByPasswordAndMfaRequest();
        KeystoneCreateUserTokenByPasswordAndMfaRequestBody body
            = new KeystoneCreateUserTokenByPasswordAndMfaRequestBody();

        // 设置scope
        AuthScope authScope = setScope();

        MfaTotpUser userTotp = new MfaTotpUser();
        userTotp.withId(userId)
            .withPasscode(passcode);
        MfaTotp totpIdentity = new MfaTotp();
        totpIdentity.withUser(userTotp);
        PwdPasswordUserDomain domainUser = new PwdPasswordUserDomain();
        domainUser.withName(domainName);
        PwdPasswordUser userPassword = new PwdPasswordUser();
        userPassword.withDomain(domainUser)
            .withName(userName)
            .withPassword(userPwd);
        PwdPassword passwordIdentity = new PwdPassword();
        passwordIdentity.withUser(userPassword);
        List<MfaIdentity.MethodsEnum> listIdentityMethods = new ArrayList<MfaIdentity.MethodsEnum>();
        listIdentityMethods.add(MfaIdentity.MethodsEnum.fromValue("password"));
        listIdentityMethods.add(MfaIdentity.MethodsEnum.fromValue(" totp"));
        MfaIdentity identityAuth = new MfaIdentity();
        identityAuth.withMethods(listIdentityMethods)
            .withPassword(passwordIdentity)
            .withTotp(totpIdentity);
        MfaAuth authbody = new MfaAuth();
        authbody.withIdentity(identityAuth)
            .withScope(authScope);
        body.withAuth(authbody);
        request.withBody(body);
        try {
            KeystoneCreateUserTokenByPasswordAndMfaResponse response = client.keystoneCreateUserTokenByPasswordAndMfa(
                request);
            logger.info(response.toString());
        } catch (ClientRequestException e) {
            LogError(e);
        }
    }

    private static void createAgencyToken(IamClient client) {
        logger.info("####createAgencyToken start!####");
        // domainId和domainName二选一
        String domainId = ""; // 委托方A的账号ID，必传
        String domainName = ""; // 委托方A的账号名称，必传
        String agencyName = ""; // 委托方A创建的委托的名称，必传

        KeystoneCreateAgencyTokenRequest request = new KeystoneCreateAgencyTokenRequest();
        KeystoneCreateAgencyTokenRequestBody body = new KeystoneCreateAgencyTokenRequestBody();

        // 设置scope，如果需要设置scop，完成setScopeForAgencyToken()方法。
        AgencyTokenScope agencyTokenScope = setScopeForAgencyToken();

        // 设置assume_role的具体信息
        AgencyTokenAssumerole assumeRoleIdentity = new AgencyTokenAssumerole();
        if (!StringUtils.isEmpty(domainId)) {
            assumeRoleIdentity.withDomainId(domainId).withAgencyName(agencyName);
        } else if (!StringUtils.isEmpty(domainName)) {
            assumeRoleIdentity.withDomainName(domainName).withAgencyName(agencyName);
        } else {
            logger.error("Need domainId or domainName!");
        }

        List<AgencyTokenIdentity.MethodsEnum> listIdentityMethods = new ArrayList<AgencyTokenIdentity.MethodsEnum>();
        listIdentityMethods.add(AgencyTokenIdentity.MethodsEnum.fromValue("assume_role"));
        AgencyTokenIdentity identityAuth = new AgencyTokenIdentity();
        identityAuth.withMethods(listIdentityMethods)
            .withAssumeRole(assumeRoleIdentity);
        AgencyTokenAuth authbody = new AgencyTokenAuth();
        authbody.withIdentity(identityAuth)
            .withScope(agencyTokenScope);
        body.withAuth(authbody);
        request.withBody(body);
        try {
            KeystoneCreateAgencyTokenResponse response = client.keystoneCreateAgencyToken(request);
            logger.info(response.toString());
        } catch (ClientRequestException e) {
            LogError(e);
        }
    }

    private static void createScopedToken(IamClient client) {
        logger.info("####createScopedToken start!####");
        String tokenId = ""; // 联邦unscoped token的信息，必传

        KeystoneCreateScopedTokenRequest request = new KeystoneCreateScopedTokenRequest();
        KeystoneCreateScopedTokenRequestBody body = new KeystoneCreateScopedTokenRequestBody();

        // 设置scope，如果需要设置scop，完成setScopeForToken方法。
        TokenSocpeOption tokenSocpeOption = setScopeForToken();

        // 设置assume_role的具体信息
        ScopedToken tokenIdentity = new ScopedToken();
        tokenIdentity.withId(tokenId);
        List<String> listIdentityMethods = new ArrayList<String>();
        listIdentityMethods.add("token");
        ScopedTokenIdentity identityAuth = new ScopedTokenIdentity();
        identityAuth.withMethods(listIdentityMethods)
            .withToken(tokenIdentity);
        ScopedTokenAuth authbody = new ScopedTokenAuth();
        authbody.withIdentity(identityAuth)
            .withScope(tokenSocpeOption);
        body.withAuth(authbody);
        request.withBody(body);
        try {
            KeystoneCreateScopedTokenResponse response = client.keystoneCreateScopedToken(request);
            logger.info(response.toString());
        } catch (ClientRequestException e) {
            LogError(e);
        }
    }

    private static AuthScope setScope() {
        // scope为domain级别时，scopeDomainId和scopeDomainName二选一
        String scopeDomainId = ""; // 租户id
        String scopeDomainName = ""; // 租户名
        // scope为project级别时，scopeProjectId和scopeProjectName二选一
        String scopeProjectId = ""; // 项目id
        String scopeProjectName = ""; // 项目名

        // 设置scope
        AuthScopeProject authScopeProject = new AuthScopeProject();
        AuthScopeDomain authScopeDomain = new AuthScopeDomain();
        AuthScope authScope = new AuthScope();
        if (!StringUtils.isEmpty(scopeDomainId)) {
            authScopeDomain.withId(scopeDomainId);
            authScope.withDomain(authScopeDomain);
        } else if (!StringUtils.isEmpty(scopeDomainName)) {
            authScopeDomain.withName(scopeDomainName);
            authScope.withDomain(authScopeDomain);
        } else if (!StringUtils.isEmpty(scopeProjectId)) {
            authScopeProject.withId(scopeProjectId);
            authScope.withProject(authScopeProject);
        } else if (!StringUtils.isEmpty(scopeProjectName)) {
            authScopeProject.withName(scopeProjectName);
            authScope.withProject(authScopeProject);
        }
        return authScope;
    }

    private static AgencyTokenScope setScopeForAgencyToken() {

        // scope为domain级别时，scopeDomainId和scopeDomainName二选一
        String scopeDomainId = ""; // 租户id
        String scopeDomainName = ""; // 租户名
        // scope为project级别时，scopeProjectId和scopeProjectName二选一
        String scopeProjectId = ""; // 项目id
        String scopeProjectName = ""; // 项目名

        // 设置scope
        AgencyTokenScopeProject agencyTokenScopeProject = new AgencyTokenScopeProject();
        AgencyTokenScopeDomain agencyTokenScopeDomain = new AgencyTokenScopeDomain();
        AgencyTokenScope agencyTokenScope = new AgencyTokenScope();
        if (!StringUtils.isEmpty(scopeDomainId)) {
            agencyTokenScopeDomain.withId(scopeDomainId);
            agencyTokenScope.withDomain(agencyTokenScopeDomain);
        } else if (!StringUtils.isEmpty(scopeDomainName)) {
            agencyTokenScopeDomain.withName(scopeDomainName);
            agencyTokenScope.withDomain(agencyTokenScopeDomain);
        } else if (!StringUtils.isEmpty(scopeProjectId)) {
            agencyTokenScopeProject.withId(scopeProjectId);
            agencyTokenScope.withProject(agencyTokenScopeProject);
        } else if (!StringUtils.isEmpty(scopeProjectName)) {
            agencyTokenScopeProject.withName(scopeProjectName);
            agencyTokenScope.withProject(agencyTokenScopeProject);
        }
        return agencyTokenScope;
    }

    private static TokenSocpeOption setScopeForToken() {
        // scope为domain级别时，scopeDomainId和scopeDomainName二选一
        String scopeDomainId = ""; // 租户id
        String scopeDomainName = ""; // 租户名
        // scope为project级别时，scopeProjectId和scopeProjectName二选一
        String scopeProjectId = ""; // 项目id

        // 设置scope
        ScopeProjectOption scopeProjectOption = new ScopeProjectOption();
        ScopeDomainOption scopeDomainOption = new ScopeDomainOption();
        TokenSocpeOption tokenSocpeOption = new TokenSocpeOption();
        if (!StringUtils.isEmpty(scopeDomainId)) {
            scopeDomainOption.withId(scopeDomainId);
            tokenSocpeOption.withDomain(scopeDomainOption);
        } else if (!StringUtils.isEmpty(scopeDomainName)) {
            scopeDomainOption.withName(scopeDomainName);
            tokenSocpeOption.withDomain(scopeDomainOption);
        } else if (!StringUtils.isEmpty(scopeProjectId)) {
            scopeProjectOption.withId(scopeProjectId);
            tokenSocpeOption.withProject(scopeProjectOption);
        }
        return tokenSocpeOption;
    }

    private static void LogError(ClientRequestException e) {
        logger.error("HttpStatusCode: " + e.getHttpStatusCode());
        logger.error("RequestId: " + e.getRequestId());
        logger.error("ErrorCode: " + e.getErrorCode());
        logger.error("ErrorMsg: " + e.getErrorMsg());
    }
}
